﻿// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "FactoryMethodPattern.generated.h"

/** 工厂方法模式 Factory Method Pattern 及自定义创建资源
 *	描述
 *		又称为工厂模式，也叫虚拟构造器(Virtual Constructor)模式，或者多态工厂(Polymorphic Factory)模式
 *		工厂父类负责定义创建产品对象的公共接口，而工厂子类则负责生成具体的产品对象，这样做的目的是将产品类的实例化操作延迟到工厂子类中完成，即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
 *	套路
 *		创建抽象产品类 ；
 *		创建具体产品类，继承抽象产品类；
 *		创建抽象工厂类
 *		创建工厂类，继承抽象工厂类，定义具体产品类的创建方法；
 *		通过调用具体工厂类的方法，从而创建不同具体产品类的实例
 *	使用场景
 *		当一个类不知道它所需要的对象的类时。使用者无需知道具体产品类的类名，只需要知道所对应的工厂即可；
 *		当一个类希望通过其子类来指定创建对象时。由子类来创建具体产品
 *	优缺点
 *		优点
 *			将创建实例的工作与使用实例的工作分开，实现了解耦；
 *			用户只需要关心所需产品对应的工厂，无须关心创建细节，甚至无须知道具体产品类的类名。
 *			加入新产品时，无须修改抽象工厂和抽象产品提供的接口，只要添加一个具体工厂和具体产品就可以了。这样更符合“开闭原则”。
 *		缺点
 *			在添加新产品时，需要编写新的具体产品类和工厂类，在一定程度上增加了系统的复杂度，
 *			引入抽象层，增加了系统的抽象性和理解难度
 *			一个具体工厂只能创建一种具体产品
 **/

// 产品抽象类
UCLASS(Abstract)
class MISCELLANEOUSPROJECT_API UFactoryMethodProduct : public UObject
{
	GENERATED_BODY()
public:
	virtual void ShowInfo()
	{
		check(0 && "You must override this");
	}
};

// 产品具体类A
UCLASS()
class MISCELLANEOUSPROJECT_API UFactoryMethodProductA : public UFactoryMethodProduct
{
	GENERATED_BODY()
public:
	virtual void ShowInfo() override
	{
		// UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" This is a ProductA"));
	}
};

// 产品具体类B
UCLASS()
class MISCELLANEOUSPROJECT_API UFactoryMethodProductB : public UFactoryMethodProduct
{
	GENERATED_BODY()
public:
	virtual void ShowInfo() override
	{
		// UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" This is a ProductB"));
	}
};

// 工厂抽象类
UCLASS(Abstract)
class MISCELLANEOUSPROJECT_API UFactoryMethodFactory : public UObject
{
	GENERATED_BODY()
public:
	virtual UFactoryMethodProduct* CreateNewProduct()
	{
		check(0 && "You must override this");
		return nullptr;
	}
};

// 工厂具体类A
UCLASS(Blueprintable,BlueprintType)
class MISCELLANEOUSPROJECT_API UFactoryMethodFactoryA : public UFactoryMethodFactory
{
	GENERATED_BODY()
public:
	virtual UFactoryMethodProduct* CreateNewProduct() override
	{
		return NewObject<UFactoryMethodProductA>();
	}
};

// 工厂具体类B
UCLASS(Blueprintable, BlueprintType)
class MISCELLANEOUSPROJECT_API UFactoryMethodFactoryB : public UFactoryMethodFactory
{
	GENERATED_BODY()
public:
	virtual UFactoryMethodProduct* CreateNewProduct() override
	{
		return NewObject<UFactoryMethodProductB>();
	}
};

// 调用测试用的Actor
UCLASS()
class MISCELLANEOUSPROJECT_API AFactoryMethodFactoryActor : public AActor
{
	GENERATED_BODY()
public:
	UPROPERTY()
	UFactoryMethodFactoryA* FactoryA;

	UPROPERTY()
	UFactoryMethodFactoryB* FactoryB;

	virtual void BeginPlay() override
	{
		// A 工厂生成 A 产品
		FactoryA = NewObject<UFactoryMethodFactoryA>();
		UFactoryMethodProduct* ProductA = FactoryA->CreateNewProduct();
		ProductA->ShowInfo();

		// B 工厂生成 B 产品
		FactoryB = NewObject<UFactoryMethodFactoryB>();
		UFactoryMethodProduct* ProductB = FactoryB->CreateNewProduct();
		ProductB->ShowInfo();
	}
};
